package action

/**
 * @Description
 * @Author 007lz
 * @Date 2024/7/12 下午2:57
 **/
import (
	"context"
	"errors"
	"fmt"
	"net/http"
	"time"

	"gitee.com/git-lz/twelve/common/consts"
	"gitee.com/git-lz/twelve/common/dto/response"
	"gitee.com/git-lz/twelve/common/httpclient"
	"gitee.com/git-lz/twelve/common/mjson"
	"gitee.com/git-lz/twelve/common/zaplog"
	"gitee.com/git-lz/twelve/logic/node"
	"gitee.com/git-lz/twelve/model/task"
	"go.uber.org/zap"
)

type Http struct {
	config  *task.HttpActionConfig
	request *httpclient.Request
	inode   node.INode
}

func NewHttpAction() *Http {
	return &Http{}
}

func (h *Http) OnPrepare(ctx context.Context, params *task.ExecActionParams) error {
	var config *task.HttpActionConfig
	if err := mjson.UnmarshalFromInterface(params.ActionInfo.Config, &config); err != nil {
		return err
	}

	h.config = config

	inode, ok := params.TaskContext.NodeMap[params.NodeId]
	if !ok {
		return errors.New(fmt.Sprintf("nodeId=(%v) not exist", params.NodeId))
	}
	request, err := inode.GetRequestParams(ctx)
	if err != nil {
		return err
	}

	h.request = request.(*httpclient.Request)
	h.inode = inode
	return nil
}

func (h *Http) Do(ctx context.Context) error {
	builder := httpclient.NewClientBuilder()
	builder.TimeOut(time.Duration(h.config.TimeoutSecond) * time.Second)
	builder.MaxRetry(h.config.RetryTimes)
	builder.BuildResponse(httpclient.EasyBuildResponse)

	client, err := builder.Build()
	if err != nil {
		return err
	}

	url, err := client.BuildUrlByParams(h.config.Url, h.request.Params)
	if err != nil {
		return err
	}

	var response httpclient.IResponse
	switch h.config.Method {
	case http.MethodGet:
		response = client.Get(ctx, url)
		if response.StatusCode() != http.StatusOK {
			return errors.New(fmt.Sprintf("request failed. response=(%v)", response.ToString()))
		}
	}

	return h.OnComplete(ctx, response.Content())
}

func (h *Http) OnComplete(ctx context.Context, resp any) error {
	start := time.Now()

	var respData *response.Response
	if err := mjson.JsonIter.Unmarshal(resp.([]byte), &respData); err != nil {
		return err
	}

	var tasks []task.Task
	if err := mjson.UnmarshalFromInterface(respData.Data, &tasks); err != nil {
		zaplog.Errorf(ctx, consts.DLTagJsonUnmarshalFailed, start, zap.Error(err))
		return err
	}

	return h.inode.SetData(ctx, tasks)
}
